package config

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/natefinch/lumberjack"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var Log *zap.SugaredLogger //全局日志对象

//config.go功能：初始化配置文件

//初始化函数
func Init() {
	//初始化配置文件
	err := initConfig()
	if err != nil {
		panic(fmt.Errorf("Fatal error config file: %s \n", err))
	}

	//初始化日志包
	Log = initLog()

	//配置文件热加载
	watchConfig()
}

//初始化配置文件
func initConfig() error {
	//解析配置文件
	viper.AddConfigPath("./conf") //指定路径
	viper.SetConfigName("config") //指定文件名
	viper.SetConfigType("yaml")   //文件类型

	//读取配置文件
	err := viper.ReadInConfig()
	if err != nil {
		return err
	} else {
		fmt.Printf("测试读取数据库名: %s \n", viper.Get("database.dbname"))
	}
	return nil
}

//初始化日志 生成一个全局可见的日志对象
//日志写入配置文件
//日志写入控制台

//日志格式 json or console ---> 详细信息

func initLog() *zap.SugaredLogger {
	//编码器
	encoder := getEncoder()
	//日志输出位置
	writeSyncer := getLogWriter()
	//日志级别
	//loglevel := zapcore.DebugLevel
	//fmt.Printf("viper.GetInt(\"log.loglevel\"): %v \n", viper.GetInt("log.logger_level"))
	loglevel := (zapcore.Level)(viper.GetInt("log.logger_level"))

	core := zapcore.NewCore(encoder, writeSyncer, loglevel)
	//生成日志对象
	logger := zap.New(core, zap.AddCaller())
	sugarLogger := logger.Sugar()
	return sugarLogger
}

//日志编码格式
func getEncoder() zapcore.Encoder {
	encoderConfig := zap.NewProductionEncoderConfig()       //标准 日志编码格式 配置
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder   //定制 日志时间类型
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder //定制 日志级别
	return zapcore.NewConsoleEncoder(encoderConfig)         //控制台格式
}

//设置日志文件相关
func getLogWriter() zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   viper.GetString("log.logger_file"),
		MaxSize:    viper.GetInt("log.logger_max_size"),
		MaxBackups: viper.GetInt("log.log_backup_count"),
		MaxAge:     viper.GetInt("log.log_save_day"),
		Compress:   viper.GetBool("log.log_rotate_compass"),
	}
	return zapcore.AddSync(lumberJackLogger)
}

//监控配置文件变化 并热加载到程序
func watchConfig() {
	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		Log.Infof("配置文件中 %s 发生更改：%s \n", e.Name, e.String())
	})
}
